package com.sdhs.paas.gateway.filter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Pattern;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.sdhs.paas.authshare.context.BaseContextHandler;
import com.sdhs.paas.gateway.config.AcmanageRuleConfig;
import com.sdhs.paas.gateway.constant.AmeConstant;
import com.sdhs.paas.gateway.model.AmeAccessPolicy;
import com.sdhs.paas.gateway.util.PaasAccessUtil;
import com.sdhs.paas.gateway.util.RequestUtils;


@Component
public class AdminAccessFilter extends ZuulFilter
{

  @Autowired
  private AcmanageRuleConfig acmanageRuleConfig;

//  @Value("${zuul.routes.menu.path}")
//  private String menuPath;
  @Value("${zuul.prefix}")
  private String zuulPrefix;
  
  public String filterType()
  {
    return "pre";
  }

  public int filterOrder()
  {
    return 10;
  }

  public boolean shouldFilter()
  {
    return true;
  }

  public Object run()
  {
    RequestContext context = RequestContext.getCurrentContext();
    String token = BaseContextHandler.getToken();
    //获取用户id
    String userId = RequestUtils.getAccountName();
    if (userId == null) {
      return null;
    }

//    if (context.getRequest().getServletPath().equals(this.menuPath)) {
//      return null;
//    }
    //获取请求路径
    String requestPath = context.getRequest().getServletPath().substring(zuulPrefix.length());
    //根据请求路径获取访问策略
    AmeAccessPolicy ameAccessPolicy = getAmeAccessPolicy(requestPath);
    //判断默认是否允许访问
    boolean isAccess = this.acmanageRuleConfig.isDefaultAccessAllowed();
    //如果根据请求路径可以获取访问策略
    if (ameAccessPolicy != null) {
//      根据userid获取可以访问的资源的列表，使用ehcache缓存资源列表
//    	isAccess = PaasAccessUtil.hasPolicy(userId);
    	//根据用户id，resource+method来判断该请求的url是否允许访问。
      isAccess = PaasAccessUtil.hasPolicy(userId, ameAccessPolicy.getResource(), ameAccessPolicy.getAction());
//      if (isAccess) {
//        List policyAttrs = PaasAccessUtil.getPolicyAttrs(accountName, ameAccessPolicy.getResource(), ameAccessPolicy.getAction());
//        context.addZuulRequestHeader("amePolicyAttrs", JSONUtil.obj2json(policyAttrs));
//      }
    }

    if (!isAccess) {
      try {
        context.getResponse().sendError(403, "access was denied");
        context.setSendZuulResponse(false);
      } catch (IOException e) {
//        PaasLogger.error("access was denied", new Object[0]);
        throw new RuntimeException("access was denied");
      }
    }
    return null;
  }

  private AmeAccessPolicy getAmeAccessPolicy(String requestPath)
  {
    List<AmeAccessPolicy> accessPolicyList = getAccessRules();

    HashMap generalMap = new HashMap();
    List<AmeAccessPolicy> regexList = new ArrayList();
    for (AmeAccessPolicy accessPolicy : accessPolicyList) {
      if (accessPolicy.getRequestPath().contains("{*}"))
        regexList.add(accessPolicy);
      else {
        generalMap.put(accessPolicy.toString(), accessPolicy);
      }
    }

    RequestContext context = RequestContext.getCurrentContext();
    AmeAccessPolicy queryAccessPolicy = new AmeAccessPolicy(requestPath, context.getRequest().getMethod());
    if (generalMap.containsKey(queryAccessPolicy.toString())) {
      return (AmeAccessPolicy)generalMap.get(queryAccessPolicy.toString());
    }
    for (AmeAccessPolicy accessPolicy : regexList) {
      if (accessPolicy.getRequestMethod().matches(context.getRequest().getMethod())) {
        String pattern = accessPolicy.getRequestPath().replace("{*}", "[\\w\\d\\.-]+");
        if (Pattern.matches(pattern, requestPath)) {
          return accessPolicy;
        }
      }
    }
    return null;
  }

  private List<AmeAccessPolicy> getAccessRules()
  {
    List accessPolicyList = new ArrayList();
    List<List<String>> accessRules = this.acmanageRuleConfig.getAccessRules();
    for (List rule : accessRules)
      if (rule.size() == AmeConstant.NumberEnum.FOUR.ordinal())
      {
        AmeAccessPolicy accessPolicy = new AmeAccessPolicy(
          (String)rule
          .get(0), 
          HttpMethod.resolve(((String)rule
          .get(1))
          .toUpperCase()), 
          (String)rule
          .get(2), 
          (String)rule
          .get(3));

        accessPolicyList.add(accessPolicy);
      }
    return accessPolicyList;
  }
  
  public static void main(String[] args) {
	  String requestUri = "/api/table/admin/user";
	  String url = "/admin/user";//
      String uri = url.replaceAll("\\{\\*\\}", "[a-zA-Z\\\\d]+");
      String regEx = "^" + uri + "$";
      System.out.println(uri);
      System.out.println(regEx);
      System.out.println(Pattern.compile(regEx).matcher(requestUri).find());
      System.out.println(requestUri.startsWith(url + "/"));
      
      String pattern = "/jwt/{*}".replace("{*}", "[\\w\\d\\.-]+");
      System.out.println(pattern);
      System.out.println(Pattern.matches(pattern, "/jwt/ntoken"));
}
}